
// ===============================================================================================================
// -*- C++ -*-
//
// Font.cpp - Bitmap font rendering/management.
//
// Copyright (c) 2011 Guilherme R. Lampert
// guilherme.ronaldo.lampert@gmail.com
//
// This code is licenced under the MIT license.
//
// This software is provided "as is" without express or implied
// warranties. You may freely copy and compile this source into
// applications you distribute provided that the copyright text
// above is included in the resulting source code.
//
// ===============================================================================================================

#include <GfxLib.hpp>

#if defined (_WIN32)

// == Local data/code ==

struct WGL_Font {

	GLuint listId;
	int fontHeight;
	HFONT hNewFont;
	HFONT hOldFont;
	HDC hDC;
};

// Currently loaded fonts.
static std::vector<WGL_Font> loadedFonts;

// ===============================================================================================================

namespace GfxLib {

int CreateBitmapFont(const char * fontName, int width, int height, bool bold, bool italic, bool underline, bool strikeout)
{
	assert(fontName != 0);

	WGL_Font wglFont;
	wglFont.fontHeight = height;
	wglFont.listId = glGenLists(maxFontChars);
	wglFont.hDC = GetDC(GetActiveWindow());
	wglFont.hNewFont = CreateFontA(height,				// Height
						width,							// Width (may be zero)
						0,								// The angle of escapement
						0,								// The angle of orientation
						(bold) ? FW_BOLD : FW_NORMAL,	// The font's weight (bold)
						(italic) ? TRUE : FALSE,		// Italic
						(underline) ? TRUE : FALSE,		// Underline
						(strikeout) ? TRUE : FALSE,		// Strikeout
						DEFAULT_CHARSET,				// Character set
						OUT_TT_PRECIS,					// The Output Precision
						CLIP_DEFAULT_PRECIS,			// The Clipping Precision
						CLEARTYPE_QUALITY,				// The quality of the font
						(FF_DONTCARE | DEFAULT_PITCH),	// The family and pitch of the font. We don't care.
						fontName);						// The font name ("Arial", "Courier", etc...)

	if (!wglFont.hNewFont)
	{
		// Error
		return (-1);
	}

	wglFont.hOldFont = (HFONT)SelectObject(wglFont.hDC, wglFont.hNewFont);

	if (!wglUseFontBitmapsA(wglFont.hDC, 0, (maxFontChars - 1), wglFont.listId))
	{
		// Error
		return (-1);
	}

	loadedFonts.push_back(wglFont);
	int fontIdx = static_cast<int>(loadedFonts.size() - 1);

	CommLib::DbgPrintf(PRINT_MSG, "Created new bitmap font: \"%s\" %d, at index: %d", fontName, height, fontIdx);

	return (fontIdx);
}

void SetTextColor(unsigned long color)
{
	glColor4ubv(reinterpret_cast<const GLubyte *>(&color));
}

void ScreenPrintf(int font, int x, int y, const char * format, ...)
{
	const int TEMP_STRING_SIZE = 2048;
	char tempString[TEMP_STRING_SIZE];

	assert(format != 0 && "Null format string !");

	if (static_cast<size_t>(font) < loadedFonts.size()) // If this is a valid font
	{
		va_list vaList;
		int n;

		va_start(vaList, format);
		n = vsnprintf(tempString, TEMP_STRING_SIZE, format, vaList);
		va_end(vaList);

		if (n > 0)
		{
			glPushAttrib(GL_LIGHTING_BIT | GL_TEXTURE_BIT);
			glDisable(GL_LIGHTING);
			glDisable(GL_TEXTURE_2D);

			glPushAttrib(GL_TRANSFORM_BIT | GL_VIEWPORT_BIT);

			glMatrixMode(GL_PROJECTION);
			glPushMatrix();
			glLoadIdentity();
			glMatrixMode(GL_MODELVIEW);
			glPushMatrix();
			glLoadIdentity();

			y = screen.height - loadedFonts[font].fontHeight - y;

			glViewport(x - 1, y - 1, 0, 0);
			glRasterPos4f(0.0f, 0.0f, 0.0f, 1.0f);

			glPopMatrix();
			glMatrixMode(GL_PROJECTION);
			glPopMatrix();

			glPopAttrib(); // GL_TRANSFORM_BIT | GL_VIEWPORT_BIT

			glPushAttrib(GL_LIST_BIT);

			glListBase(loadedFonts[font].listId);

			glCallLists(n, GL_UNSIGNED_BYTE, tempString);

			glPopAttrib(); // GL_LIST_BIT

			glPopAttrib(); // GL_LIGHTING_BIT | GL_TEXTURE_BIT
		}
	}
}

void CleanupFonts(void)
{
	size_t n = loadedFonts.size();

	while (n--)
	{
		WGL_Font & font = loadedFonts[n];

		glDeleteLists(font.listId, maxFontChars);
		SelectObject(font.hDC, font.hOldFont);
		DeleteObject(font.hNewFont);
	}

	loadedFonts.clear();

	CommLib::DbgPrintf(PRINT_MSG, "All fonts unloaded!");
}

}; // namespace GfxLib {}

#else
#error Windows specific code !
#endif // _WIN32